#!/usr/bin/env python

'''
A script for building Firefox extensions
(c) 2007 Reinis Ivanovs <dabas@untu.ms>

Available under the BSD-new terms.
'''

import zipfile
import re
import os

from zipfile import ZipFile, ZipInfo
from glob import iglob
from os import path


__version__ = '0.1'


class Build(object):
    manifest_name = 'chrome.manifest'
    chrome_name = 'chrome'
    builds = 'inst'

    def __init__(self):
        self.manifest = self.load_manifest()
        self.name = self.get_name()

    def get_name(self):
        '''Get the extension name, assuming it's in the new style format'''
        cwd = os.getcwd()
        return cwd[cwd.rfind(os.sep)+1:cwd.find('@')]

    def load_manifest(self):
        '''Parse the chrome manifest'''
        results = []
        for line in open(self.manifest_name, 'r'):
            line = line.strip()
            if not line: continue
            while (line.find('  ') != -1):
                line = line.replace('  ', ' ')
            data = line.split(' ')
            results += [data]
        return results

    def start(self):
        '''Build the XPI file'''
        inst = open('install.rdf', 'r').read()
        ver = inst[inst.find('<em:version>')+12:inst.find('</em:version>')].strip()
        #~ re,fu
        if not path.exists(self.chrome_name):
            os.mkdir(self.chrome_name)
        manifest_text = ''
        jar = ZipFile(path.join(self.chrome_name, self.name + '.jar'), 'w')
        jared = []
        for item in self.manifest:
            if item[0] in ['content', 'locale', 'skin']:
                x = item[-1][:item[-1].find('/')]
                archive(jar, x)
                jared += [x]
                item[-1] = 'jar:%s/%s.jar!/' % (self.chrome_name, self.name) \
                    + item[-1]
            manifest_text += ' '.join(item) + '\n'
        jar.close()
        cwd = os.getcwd()
        file = ZipFile(self.name + '-' + ver + '.xpi', 'w')
        archive(file, exclude_names=jared+[self.manifest_name]+['update.rdf', \
            'cap', 'RECYCLER'])
        file.writestr(ZipInfo(self.manifest_name), manifest_text)
        file.close()
        os.chdir(cwd)
        os.remove(path.join(self.chrome_name, self.name + '.jar'))
        os.rmdir(self.chrome_name)


def archive(file, source=['.'], level=0, exclude_ext=['txt', 'py', 'xpi', 'swf'], \
        exclude_names=[]):
    '''Add files to a ZIP archive'''
    if not type(source) is list:
        source = [source]
    os.chdir(source[-1])
    names = [x for x in iglob('*') if not x in exclude_names]
    for item in names:
        if (path.isdir(item)):
            archive(file, source+[item], level+1)
            continue
        if (item[item.rfind('.')+1:] in exclude_ext):
            continue
        file.write(item, '/'.join(source+[item]), zipfile.ZIP_DEFLATED)
    os.chdir('..')

def main():
    build = Build()
    build.start()

if __name__ == '__main__':
    main()
